using System.Collections.Generic;
using System;
using System.Reflection;
namespace Estoque.Core.Negocio.Enumeradores
{
    [Serializable]
    public abstract class EnumeradorSeguro<T, K> : IEnumeradorSeguro<K> where T : IEnumeradorSeguro<K>
    {
        public delegate string ObtenhaDescricaoDelegate();

        private ObtenhaDescricaoDelegate descricaoDelegate;

        protected EnumeradorSeguro(K Codigo, ObtenhaDescricaoDelegate DescricaoDelegate)
        {
            this.Codigo = Codigo;
            this.descricaoDelegate = DescricaoDelegate;
        }

        protected EnumeradorSeguro(K Codigo, string Descricao) : this(Codigo, () => Descricao) { }

        public K Codigo
        {
            get;
            protected set;
        }

        public string Descricao
        {
            get { return descricaoDelegate(); }
            protected set { descricaoDelegate = () => value; }
        }

        public override bool Equals(object obj)
        {
            return (obj as EnumeradorSeguro<T, K>) != null && ((EnumeradorSeguro<T, K>)obj).Codigo.Equals(Codigo);
        }
        public bool Equals(EnumeradorSeguro<T, K> obj)
        {
            return (obj != null) && ((EnumeradorSeguro<T, K>)obj).Codigo.Equals(Codigo);
        }
        public override string ToString()
        {
            return this.Descricao;
        }

        public override int GetHashCode()
        {
            return this.Codigo.GetHashCode(); ;
        }

        public static T Obtenha(K Codigo)
        {
            IList<T> todos = ObtenhaTodos();

            foreach (T item in todos)
            {
                if (item.Codigo.Equals(Codigo))
                    return item;
            }

            return default(T);
        }

        public static List<T> ObtenhaTodos()
        {
            List<T> todos = new List<T>();

            Type tipo = typeof(T);

            foreach (FieldInfo campo in tipo.GetFields(BindingFlags.Static | BindingFlags.Public))
            {
                T item = (T)campo.GetValue(null);
                todos.Add(item);
            }

            return todos;
        }
    }
}